package com.zifeng.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zifeng.common.Query;
import com.zifeng.common.R;
import com.zifeng.constant.RedisConstants;
import com.zifeng.dao.AssignmentDao;
import com.zifeng.feign.OrderFeignClient;
import com.zifeng.pojo.Assignment;
import com.zifeng.pojo.Order;
import com.zifeng.rocketmq.OrderRocketMQProducer;
import com.zifeng.service.IAssignmentService;
import com.zifeng.utils.BloomFilterUtil;
import com.zifeng.utils.PageUtils;
import com.zifeng.utils.RedisUtils;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.seata.spring.annotation.GlobalTransactional;
import org.redisson.api.RBloomFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.zifeng.constant.RedisConstants.*;

/**
 * 船舶委托Service业务层处理
 * 
 * @author zifeng
 * @date 2025-03-27
 */
@Slf4j
@Service("assignmentService")
public class AssignmentServiceImpl extends ServiceImpl<AssignmentDao, Assignment> implements IAssignmentService
{
    @Autowired
    private AssignmentDao assignmentDao;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private BloomFilterUtil bloomFilterUtil;

    private RBloomFilter<Long> assignmentIdBloomFilter;

    @Resource
    private OrderFeignClient orderFeignClient;

    @Autowired
    private OrderRocketMQProducer orderRocketMQProducer;

    @PostConstruct
    public void init() {
        assignmentIdBloomFilter = bloomFilterUtil.create(ASSIGNMENT_ID_BLOOM_FILTER,
                EXPECTED_INSERTIONS,
                FALSE_PROBABILITY);
        List<Assignment> list = list();
        for (Assignment assignment : list) {
            Long id = assignment.getId();
            assignmentIdBloomFilter.add(id);
        }
    }

    @Override
    public void aggregateAssignments(int id, int clientId) {
        // 1, 修改委托的买家人ID
        UpdateWrapper updateWrapper = new UpdateWrapper();
        updateWrapper.eq("id", id);
        updateWrapper.set("client_id", clientId);
        assignmentDao.update(null, updateWrapper);
        Assignment assignment = assignmentDao.selectById(id);

        // 2. 创建订单
        Order order = new Order();
        order.setAssignmentId(id);
        order.setStatus(0);
        order.setPrice(assignment.getPrice());
        order.setCreateAt(new Date());
//        orderDao.insert(order);
//        orderFeignClient.addOrderWithBlock(order);

        // 3. 将订单添加到区块链中  改成RocketMQ消息通知
//        blockFeignClient.mine(order);
        orderRocketMQProducer.sendTransactionMessage("order-transaction-topic", order);
    }

    @GlobalTransactional
    public void doMysqlLocalTransaction(Order order) {
        orderFeignClient.addOrderWithBlock(order);
    }

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        QueryWrapper<Assignment> wrapper = new QueryWrapper<>();
        Object userId = params.get("userId");
        if(userId != null) {
            int newUserId = Integer.parseInt((String) userId);
            wrapper.eq("master_id", newUserId).or().eq("client_id", newUserId);
        }
        boolean background = params.get("background") != null;
        if (userId == null && !background) { // 查全部并且是前台页面时只需要未完成状态的委托
            wrapper.eq("status", 0);
        }
        IPage<Assignment> page = this.page(
                new Query<Assignment>().getPage(params),
                wrapper
        );

        return new PageUtils(page);
    }

    /**
     * 查询委托
     * 
     * @param id 委托主键
     * @return 委托
     */
    @Override
    public Assignment selectAssignmentById(Long id)
    {
        // 使用布隆过滤器判断是否存在
        if(!assignmentIdBloomFilter.contains(id)) {
            log.info("Assignment ID {} not found in bloom filter, returning null", id);
            redisUtils.set(ASSIGNMENT_PREFIX + id, "null", ASSIGNMENT_NULL_TTL, TTL_TIME_UNIT);
            return null;
        }
        String assignmentKey = ASSIGNMENT_PREFIX + id;
        Assignment assignment = JSON.parseObject(redisUtils.get(assignmentKey), Assignment.class);
        if(assignment != null) return assignment;
        assignment = assignmentDao.selectById(id);
        redisUtils.set(assignmentKey, JSON.toJSONString(assignment), ASSIGNMENT_TTL, TTL_TIME_UNIT);
        return assignment;
    }

    /**
     * 新增委托
     * 
     * @param assignment 委托
     * @return 结果
     */
    @Override
    public int insertAssignment(Assignment assignment)
    {
        return assignmentDao.insert(assignment);
    }

    /**
     * 修改委托
     * 
     * @param assignment 委托
     * @return 结果
     */
    @Override
    public int updateAssignment(Assignment assignment)
    {
        return assignmentDao.updateById(assignment);
    }

    /**
     * 批量删除委托
     * 
     * @param ids 需要删除的委托主键
     * @return 结果
     */
    @Override
    public int deleteAssignmentByIds(Long[] ids)
    {
        return assignmentDao.deleteBatchIds(Arrays.asList(ids));
    }

    /**
     * 删除委托信息
     * 
     * @param id 委托主键
     * @return 结果
     */
    @Override
    public int deleteAssignmentById(Long id)
    {
        return assignmentDao.deleteById(id);
    }
}
